#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"../include/main.h"
#include"../include/narrtree.h"
#include"../include/constants.h"
#include"../include/vfs_errorcodes.h"
#include"../include/hash.h"
#include"../include/bst.h"
#include"../include/mount_vfs.h"

int blknum,filesize,ftype;

ntree *create(fdesc *itemdesc)
{
	ntree *temp1;
	int i=0;
	temp1=(ntree *)malloc(sizeof(ntree));
	if(temp1!=NULL)
	{
		temp1->file_desc=(fdesc *)malloc(sizeof(fdesc));
		strcpy(temp1->file_desc->filepath,itemdesc->filepath);	
		strcpy(temp1->file_desc->filename,itemdesc->filename);
		temp1->file_desc->filetype=itemdesc->filetype;
		temp1->file_desc->file_size=itemdesc->file_size;
		temp1->file_desc->blk_num=itemdesc->blk_num;
		temp1->first=NULL;
		temp1->parent=NULL;
		temp1->next=NULL;
	}
	return temp1;
}


ntree *delete_ntree(ntree *head,fdesc *itemdesc)
{
	ntree *temp2,*prev;
	char t[MAX_PATH],*s1=" ",*s2[20],*s3,*root;
	char *concat="/",s4[MAX_PATH];
	int j=0,i=0,k=0;
	while(itemdesc->filepath[i] != '\0')
	{
		t[i]=itemdesc->filepath[i];	
		i++;
	}
	t[i]='\0';
	
	while(*s1!='\0')
	{
		if(j==0)
		{
		strtok_r(t,"/",&s1);
		s2[j++]=t;
		}
		else
		{
		s3=s2[j-1];
		strtok_r(s3,"/",&s1);
		}
		s2[j++]=s1;
	}
	temp2=head;
	root=(char *)malloc(sizeof(char)*32);
	strncpy(root,s2[0],1);
	i=j;
	while(i>1){
		s2[i-1]=(char *)malloc(sizeof(char)*MAX_PATH);
		strcpy(s2[i-1],s2[i-2]);
		i--;
	}
	root[1]='\0';
	strcpy(s2[0],root);
	if(head != NULL)
	{
		if(!strcmp(s2[0],head->file_desc->filepath))
		{
			for(i=0;i<j-1;i=i++)
			{	
			
				if(i>1)
				{
					strcpy(s4,s2[i-1]);
					strcat(s4,concat);
					strcat(s4,s2[i]);
					s2[i]=s4;
				}
				while(strcmp(s2[i],temp2->file_desc->filepath) && temp2->next != NULL)	
					temp2=temp2->next;
				if(!strcmp(s2[i],temp2->file_desc->filepath))
				{
					prev=temp2;
					temp2=temp2->first;
				}
			}
			if(i>1)
			{
				strcpy(s4,s2[i-1]);
				strcat(s4,concat);
				strcat(s4,s2[i]);
				s2[i]=s4;
			}		
		}
		else
		{
			if(itemdesc->filetype==0)
				printf("%s_FAILURE %s\n",glb_command,ERR_VFS_REMOVEFILE_01);
			else
				printf("%s_FAILURE %s\n",glb_command,ERR_VFS_DELETEDIR_01);
			return NULL;
		}
		if(temp2 == NULL)
		{
			if(itemdesc->filetype==0)
				printf("%s_FAILURE %s\n",glb_command,ERR_VFS_REMOVEFILE_01);
			else
				printf("%s_FAILURE %s\n",glb_command,ERR_VFS_DELETEDIR_01);
			return NULL;
		}
		else
		{
			while(strcmp(s2[i],temp2->file_desc->filepath) && temp2->next != NULL)
			{	
				k++;
				prev=temp2;
				temp2=temp2->next;
			}
			if(!strcmp(temp2->file_desc->filepath,s2[i]))
			{ 
				if(temp2->first != NULL)
				{
					printf("%s_FAILURE %s\n",glb_command,ERR_VFS_DELETEDIR_02);
					return NULL;
				}
				else 
				{
					if(k==0)
						prev->first=temp2->next;	
					else
						prev->next=temp2->next;
					free(temp2);
				}
			}
			else
				return head;	
		}
	}
	else
		printf("%s_FAILURE %s\n",glb_command,ERR_VFS_DELETEDIR_01);
	return head;
}

ntree *insert_ntree(ntree *head,fdesc *itemdesc)
{
	ntree *temp3,*q,*parent,*temp4;
	llist *list;
	char *s1=" ",*s2[20],*s3,*concat="/",*root,*bak_s2[20];
	char t[MAX_PATH],s4[MAX_PATH],bak_s4[MAX_PATH],*bak,tp[MAX_NAME];
	int i=0,j,k,l,cnt1=0,cnt2=0,cnt3=0;
	temp3=head;
	char *pch,*pcch;
	fdesc *new;


	while(itemdesc->filepath[i] != '\0')
	{
		t[i]=itemdesc->filepath[i];	
		i++;
	}
	j=0;
	t[i]='\0';
	
	while(*s1!='\0')
	{
		if(j==0)
		{
		strtok_r(t,"/",&s1);
		s2[j++]=t;
		}
		else
		{
		s3=s2[j-1];
		strtok_r(s3,"/",&s1);
		}
		s2[j++]=s1;
	}
	root=(char *)malloc(sizeof(char)*32);
	strncpy(root,s2[0],1);
	i=j;
	while(i>1){
		s2[i-1]=(char *)malloc(sizeof(char)*MAX_PATH);
		strcpy(s2[i-1],s2[i-2]);
		i--;
	}
	root[1]='\0';
	strcpy(s2[0],root);
	for(i=0;i<j;i++)
	{
		bak_s2[i]=(char *)malloc(sizeof(char)*MAX_PATH);
		strcpy(bak_s2[i],s2[i]);
	}
	
	q=create(itemdesc);
	if(!strcmp(s2[0],head->file_desc->filepath))
	{
		for(i=0;i<j-1;i++)
		{
			if(i>1)
			{
				strcpy(s4,s2[i-1]);
				strcat(s4,concat);
				strcat(s4,s2[i]);
				s2[i]=s4;
			}
			if(temp3!=NULL){
			while(strcmp(s2[i],temp3->file_desc->filepath) && temp3->next != NULL)	
				temp3=temp3->next;
			if(!strcmp(s2[i],temp3->file_desc->filepath))
			{
				cnt3++;
				parent=temp3;
				temp3=temp3->first;
			}
			}
		}
		if(i>1)
		{
			strcpy(s4,s2[i-1]);
			strcat(s4,concat);
			strcat(s4,s2[i]);
			s2[i]=s4;
		}
	}
	else
		return head;
	if(temp3 == NULL && i >= (j-2))
	{
		if(j>2 && local_used_fd==1)
		{
			blknum=itemdesc->blk_num;
			filesize=itemdesc->file_size;
			ftype=itemdesc->filetype;
			temp4=head;
			l=1;
			new=(fdesc *)malloc(sizeof(fdesc));
			strcpy(new->filename,bak_s2[l]);
			pch=strchr(new->filename,'/');
			pch++;
			strcpy(new->filename,pch);
			strcpy(new->filepath,bak_s2[l]);
			new->filetype=1;
			new->file_size=0;
			new->blk_num=0;
			if(local_used_fd < local_max_fd)
			{
				head=insert_ntree(head,new);
				list=insert(new);
				local_used_fd++;
				temp4=head;
				fun(temp4,cnt3+1,bak_s2,j);
				return head;
			}
			else
			{
				printf("%s_FAILURE %s\n",glb_command,ERR_VFS_MAKEDIR_01);
				return head;
			}
		}
		if(j>3 && local_used_fd == 2)
		{
			blknum=itemdesc->blk_num;
			filesize=itemdesc->file_size;
			ftype=itemdesc->filetype;
			temp4=head;
			l=2;
			new=(fdesc *)malloc(sizeof(fdesc));
			strcpy(new->filename,bak_s2[l]);
			strcpy(new->filepath,bak_s2[l-1]);
			strcat(new->filepath,concat);
			strcat(new->filepath,bak_s2[l]);			
			new->filetype=1;
			new->file_size=0;
			new->blk_num=0;
			if(local_used_fd < local_max_fd)
			{
				head=insert_ntree(head,new);
				list=insert(new);
				local_used_fd++;
				temp4=head;
				fun(temp4,cnt3+1,bak_s2,j);
				return head;
			}
			else
			{
				printf("%s_FAILURE %s\n",glb_command,ERR_VFS_MAKEDIR_01);
				return head;
			}
		}
		if(cnt3 == j-1)
		{
			//printf("cnt3==%d,j==%d\n",cnt3,j);
			parent->first=q;
			q->parent=parent;
		}
		else
		{
			blknum=itemdesc->blk_num;
			filesize=itemdesc->file_size;
			ftype=itemdesc->filetype;
			temp4=head;
			fun(temp4,cnt3,bak_s2,j);
			return head;
		}
	}
	else
	{	
		if(temp3!=NULL && cnt3 == j-1)
		{
			while(strcmp(s2[i],temp3->file_desc->filepath) && temp3->next != NULL)
				temp3=temp3->next;
			temp3->next=q;
			q->next=NULL;
			return head;
		}
		if(temp3==NULL)
		{
			
			//else
			//{
				blknum=itemdesc->blk_num;
				filesize=itemdesc->file_size;
				ftype=itemdesc->filetype;
				temp4=head;
				fun(temp4,cnt3,bak_s2,j);
				return head;
			//}
		}
		while(strcmp(s2[i],temp3->file_desc->filepath) && temp3->next != NULL)
		{
			temp3=temp3->next;
		}
		if(!strcmp(temp3->file_desc->filepath,s2[i]))
		{
			return head;
		}
		else
		{
			
			pch=strchr(s2[i],'/');
			
  			while (pch!=NULL) {
				cnt1++;
				pch=strchr(pch+1,'/');
			}
			pch=strchr(temp3->file_desc->filepath,'/');
  			while (pch!=NULL) {
				cnt2++;
				pch=strchr(pch+1,'/');
			}
			if(cnt1==cnt2)
			{
				q->next=temp3->next;
				temp3->next=q;
				q->parent=temp3->parent;
			}
			else
			{				
				temp4=head;
				blknum=itemdesc->blk_num;
				filesize=itemdesc->file_size;
				ftype=itemdesc->filetype;
				fun(temp4,cnt3,bak_s2,j);
				return head;
			}
		}			
	}
	return head;	
}

void fun(ntree *temp4,int cnt3,char *bak_s2[],int j)
{
	int l,t;
	ntree *parent;
	char bak_s4[MAX_PATH],*concat="/",*pch,tp[MAX_NAME];
	fdesc *new;
	llist *list;
	for(l=0;l<cnt3;l++)
	{
		if(l>1)
		{
			strcpy(bak_s4,bak_s2[l-1]);
			strcat(bak_s4,concat);
			strcat(bak_s4,bak_s2[l]);
			bak_s2[l]=bak_s4;
		}
		while(strcmp(bak_s2[l],temp4->file_desc->filepath) && temp4->next != NULL)	
			temp4=temp4->next;
		if(!strcmp(bak_s2[l],temp4->file_desc->filepath))
		{
			parent=temp4;
			temp4=temp4->first;
		}
	}
	while(l<j)
	{						
		new=(fdesc *)malloc(sizeof(fdesc));
		strcpy(new->filename,bak_s2[l]);
		pch=strrchr(new->filename,'/');
		if(pch!=NULL)
		{
			pch++;
			strcpy(tp,pch);
			strcpy(new->filename,tp);
		}
		strcpy(new->filepath,bak_s2[l-1]);
		if(strcmp(new->filepath,"/"))
			strcat(new->filepath,concat);
		if(l==1)
		strcat(new->filepath,tp);
		else
		strcat(new->filepath,bak_s2[l]);
		if(l != j-1)
		{
			new->filetype=1;
			new->file_size=0;
			new->blk_num=0;
		}
		else
		{
			new->filetype=ftype;
			new->file_size=filesize;
			new->blk_num=blknum;
		}
		if(local_used_fd < local_max_fd)
		{
			head=insert_ntree(head,new);
			list=insert(new);
			local_used_fd++;
			strcpy(bak_s4,bak_s2[l-1]);
			if(strcmp(bak_s4,"/"))
				strcat(bak_s4,concat);
			if(l==1)
			{
				pch=strrchr(bak_s2[l],'/');
				pch++;
				strcat(bak_s4,pch);
			}
			else
				strcat(bak_s4,bak_s2[l]);
			bak_s2[l]=bak_s4;
			l++;
		}
		else
		{
			l=j;
			printf("%s_FAILURE %s\n",glb_command,ERR_VFS_MAKEDIR_01);
		}
	}
	local_used_fd--;
}

void traverse(ntree *head)
{
	ntree *temp4,*q;
	q=head;
	if(q!=NULL)
	{
		temp4=q;
		do
		{
			printf("%s\t %d\t %d\n",temp4->file_desc->filepath,temp4->file_desc->blk_num,temp4->file_desc->filetype);
			traverse(temp4->first);
			temp4=temp4->next;
		}while(temp4!=NULL);
		q=q->first;
	}
}

ntree *search_node(ntree *head,char filepath[MAX_PATH])
{
	ntree *temp4,*q,*ret;
	q=head;
	if(q!=NULL)
	{
		temp4=q;
		do
		{
			if(!strcmp(temp4->file_desc->filepath,filepath))
			{
				schflag=1;
				return temp4;
			}
			ret=search_node(temp4->first,filepath);
			if(schflag==1)
				return ret;
			temp4=temp4->next;
		}while(temp4!=NULL);
		q=q->first;
	}
	if(schflag==0)
		return NULL;
}
